1 /*
2 * Copyright (C) 2007 The Guava Authors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package com.google.common.io;
18
19 import static com.google.common.base.Preconditions.checkArgument;
20 import static com.google.common.base.Preconditions.checkNotNull;
21
22 import com.google.common.annotations.Beta;
23 import com.google.common.base.Charsets;
24 import com.google.common.base.MoreObjects;
25 import com.google.common.collect.Lists;
26
27 import java.io.IOException;
28 import java.io.InputStream;
29 import java.io.OutputStream;
30 import java.net.URL;
31 import java.nio.charset.Charset;
32 import java.util.List;
33
34 /**
35 * Provides utility methods for working with resources in the classpath.
36 * Note that even though these methods use {@link URL} parameters, they
37 * are usually not appropriate for HTTP or other non-classpath resources.
38 *
39 * <p>All method parameters must be non-null unless documented otherwise.
40 *
41 * @author Chris Nokleberg
42 * @author Ben Yu
43 * @author Colin Decker
44 * @since 1.0
45 */
46 @Beta
47 public final class Resources {
48 private Resources() {}
49
50 /**
51 * Returns a {@link ByteSource} that reads from the given URL.
52 *
53 * @since 14.0
54 */
55 public static ByteSource asByteSource(URL url) {
56 return new UrlByteSource(url);
57 }
58
59 /**
60 * A byte source that reads from a URL using {@link URL#openStream()}.
61 */
62 private static final class UrlByteSource extends ByteSource {
63
64 private final URL url;
65
66 private UrlByteSource(URL url) {
67 this.url = checkNotNull(url);
68 }
69
70 @Override
71 public InputStream openStream() throws IOException {
72 return url.openStream();
73 }
74
75 @Override
76 public String toString() {
77 return "Resources.asByteSource(" + url + ")";
78 }
79 }
80
81 /**
82 * Returns a {@link CharSource} that reads from the given URL using the given
83 * character set.
84 *
85 * @since 14.0
86 */
87 public static CharSource asCharSource(URL url, Charset charset) {
88 return asByteSource(url).asCharSource(charset);
89 }
90
91 /**
92 * Reads all bytes from a URL into a byte array.
93 *
94 * @param url the URL to read from
95 * @return a byte array containing all the bytes from the URL
96 * @throws IOException if an I/O error occurs
97 */
98 public static byte[] toByteArray(URL url) throws IOException {
99 return asByteSource(url).read();
100 }
101
102 /**
103 * Reads all characters from a URL into a {@link String}, using the given
104 * character set.
105 *
106 * @param url the URL to read from
107 * @param charset the charset used to decode the input stream; see {@link
108 * Charsets} for helpful predefined constants
109 * @return a string containing all the characters from the URL
110 * @throws IOException if an I/O error occurs.
111 */
112 public static String toString(URL url, Charset charset) throws IOException {
113 return asCharSource(url, charset).read();
114 }
115
116 /**
117 * Streams lines from a URL, stopping when our callback returns false, or we
118 * have read all of the lines.
119 *
120 * @param url the URL to read from
121 * @param charset the charset used to decode the input stream; see {@link
122 * Charsets} for helpful predefined constants
123 * @param callback the LineProcessor to use to handle the lines
124 * @return the output of processing the lines
125 * @throws IOException if an I/O error occurs
126 */
127 public static <T> T readLines(URL url, Charset charset,
128 LineProcessor<T> callback) throws IOException {
129 return asCharSource(url, charset).readLines(callback);
130 }
131
132 /**
133 * Reads all of the lines from a URL. The lines do not include
134 * line-termination characters, but do include other leading and trailing
135 * whitespace.
136 *
137 * <p>This method returns a mutable {@code List}. For an
138 * {@code ImmutableList}, use
139 * {@code Resources.asCharSource(url, charset).readLines()}.
140 *
141 * @param url the URL to read from
142 * @param charset the charset used to decode the input stream; see {@link
143 * Charsets} for helpful predefined constants
144 * @return a mutable {@link List} containing all the lines
145 * @throws IOException if an I/O error occurs
146 */
147 public static List<String> readLines(URL url, Charset charset)
148 throws IOException {
149 // don't use asCharSource(url, charset).readLines() because that returns
150 // an immutable list, which would change the behavior of this method
151 return readLines(url, charset, new LineProcessor<List<String>>() {
152 final List<String> result = Lists.newArrayList();
153
154 @Override
155 public boolean processLine(String line) {
156 result.add(line);
157 return true;
158 }
159
160 @Override
161 public List<String> getResult() {
162 return result;
163 }
164 });
165 }
166
167 /**
168 * Copies all bytes from a URL to an output stream.
169 *
170 * @param from the URL to read from
171 * @param to the output stream
172 * @throws IOException if an I/O error occurs
173 */
174 public static void copy(URL from, OutputStream to) throws IOException {
175 asByteSource(from).copyTo(to);
176 }
177
178 /**
179 * Returns a {@code URL} pointing to {@code resourceName} if the resource is
180 * found using the {@linkplain Thread#getContextClassLoader() context class
181 * loader}. In simple environments, the context class loader will find
182 * resources from the class path. In environments where different threads can
183 * have different class loaders, for example app servers, the context class
184 * loader will typically have been set to an appropriate loader for the
185 * current thread.
186 *
187 * <p>In the unusual case where the context class loader is null, the class
188 * loader that loaded this class ({@code Resources}) will be used instead.
189 *
190 * @throws IllegalArgumentException if the resource is not found
191 */
192 public static URL getResource(String resourceName) {
193 ClassLoader loader = MoreObjects.firstNonNull(
194 Thread.currentThread().getContextClassLoader(),
195 Resources.class.getClassLoader());
196 URL url = loader.getResource(resourceName);
197 checkArgument(url != null, "resource %s not found.", resourceName);
198 return url;
199 }
200
201 /**
202 * Given a {@code resourceName} that is relative to {@code contextClass},
203 * returns a {@code URL} pointing to the named resource.
204 *
205 * @throws IllegalArgumentException if the resource is not found
206 */
207 public static URL getResource(Class<?> contextClass, String resourceName) {
208 URL url = contextClass.getResource(resourceName);
209 checkArgument(url != null, "resource %s relative to %s not found.",
210 resourceName, contextClass.getName());
211 return url;
212 }
213 }